package nancal.mp

import feign.FeignException
import io.kubernetes.client.openapi.ApiException
import io.lettuce.core.RedisCommandTimeoutException
import nbcp.base.comm.JsonResult
import nbcp.base.extend.*
import nbcp.mvc.sys.WriteJsonRawValue
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseBody
import javax.crypto.BadPaddingException
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import kotlin.jvm.optionals.getOrNull

@ControllerAdvice
@ResponseBody
class GlobalProcController {
    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }

    @ExceptionHandler(Throwable::class)
    fun exp(ex: Throwable, request: HttpServletRequest, response: HttpServletResponse) {
        logger.error("", ex)

        if (response.status == 401) {
            return
        }

        if (response.status.IsInItems(200, 299)) {
            response.status = 500
        }

        var error = ex.cause ?: ex;

        if (error is FeignException) {
            logger.error(error.message, error)

            response.WriteJsonRawValue(
                JsonResult.error(
                    "Feign: " + (error.responseBody()
                        .getOrNull()?.toByteArray()?.toUtf8String()
                        .AsString(error.message.AsString())).Slice(0, 1024),
                    -error.status()
                )
                    .ToJson()
            )
            return;
        } else if (error is ApiException) {
            logger.error(error.message, error)
            response.WriteJsonRawValue(
                JsonResult.error(
                    "K8sApi:" + error.responseBody,
                    -error.code
                )
                    .ToJson()
            )

            return;
        } else if (error is RedisCommandTimeoutException) {
            logger.error(error.message, error);
            response.WriteJsonRawValue(
                JsonResult.error(
                    "无法连接Redis!"
                )
                    .ToJson()
            )
            return;
        }


        //ex.cause 可能是 RuntimeException包装的异常
        response.WriteJsonRawValue(getExceptionSafeMessage(error).ToJson())
    }

    private fun getExceptionSafeMessage(error: Throwable): JsonResult {
        if (error is BadPaddingException) {
            return JsonResult.error("RSA解密错误", -1)
        }

        return JsonResult.error(error.javaClass.simpleName + ": " + error.message.AsString(), -1)
    }
}